#ifndef WORLD_H_
#define WORLD_H_

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <list>
#include "../GObj/Object.h"
#include "irrlicht.h"

namespace Facets {

	/**
	 * CameraFactory is the creation method for Irrlicht cameras (and eventually, the
	 * Facets standalone Camera class) intended to modularize the use of cameras without
	 * requiring the Entity class to know what kind of camera it is getting, or how to
	 * create it. Everything is handled via the factory.
	 */
	class CameraFactory {
		/// Irrlicht scene manager in use by Facets
		scene::ISceneManager* m_SceneManager;
		public: 
			/**
			 * Initializes CameraFactory and assigns m_SceneManager a value.
			 * @param smgr The current scene manager from Irrlicht
			 */
			CameraFactory(scene::ISceneManager* smgr) {
				m_SceneManager = smgr;
			}
			/**
			 * Returns a Boost shared_ptr to a camera created within the Irrlicht device
			 * context, m_SceneManager.
			 * @param pos Position of the camera.
			 * @param dir Direction of the camera.
			 * @return A boost shared_ptr of the camera handle.
			 */
			boost::shared_ptr<irr::scene::ICameraSceneNode> CreateCamera(irr::core::vector3df pos,
											irr::core::vector3df dir) {
				irr::scene::ICameraSceneNode* lol = m_SceneManager->addCameraSceneNodeFPS();
				return boost::shared_ptr<irr::scene::ICameraSceneNode>(lol); 		
		} 
	};

	/**
	 * @brief Holds the world state, as well as maps. 
	 * 
	 * Encapsulates the state of the world, including what map(s) are currently loaded and in use,
	 * as well as what state the world is in for this client (lobby, in play, loading/saving, dead
	 * etc.
	 */
	class World {
		/// Enumeration for states the world can be in.
		enum _e_state { WORLD_LOADING, WORLD_IN_PLAY, WORLD_LOBBY, WORLD_SAVING, WORLD_DEAD };
		/// Holds the world state.
		_e_state m_WorldState;
		
		/// Holds a list of the objects in the world; will move this to Maps subsequently
		std::list<Object*> m_objectList;
		
		/// Holds the world camera factory
		static CameraFactory* m_cameraFactory;
		
		bool m_quit;
		
		public:
			World();
			virtual ~World();
			
			/**
			 * @brief Used to initialize the camera factory for use
			 * @return True if the factory initialized properly, false if there was a problem
			 */
			bool initializeCameraFactory();
			
			/**
			 * @brief Returns a copy of the camera factory
			 * @return A pointer to the world camera factory
			 */
			static CameraFactory* GetCameraFactory();
			
			bool addObject(Object* obj) {
				try {
					m_objectList.push_back(obj);
				}
				catch(std::exception& e) {
					std::cout<<"Standard exception:: "<<e.what()<<std::endl;
				}
				catch(...) {
					std::cout<<"Unknown error occurred, throwing."<<std::endl;
					throw;
				}
			}
			
			void update(float dt) {
				std::list<Object*>::iterator iter;
				for(iter = m_objectList.begin(); iter != m_objectList.end();
						iter++)
					(*iter)->update(dt);
			}
			
	};
}

#endif /*WORLD_H_*/
